import os
import shutil
from datetime import datetime
from tkinter import Tk, Label, Entry, Button, filedialog, messagebox
from concurrent.futures import ThreadPoolExecutor, as_completed
import tkinter as tk

# Configuration parameters
EXCLUDE_DIRS = {"node_modules", ".git", "target", ".idea", "dist"}
EXCLUDE_EXTENSIONS = {".class", ".tmp", ".env", ".env.development", ".editorconfig", ".env.production", ".lock", ".bak",
                      ".imp", ".log", ".swp", ".class", ".jar", ".war", ".ear", ".zip", ".rar", ".7z", ".gz", ".tar",
                      ".tgz", ".tar.gz", ".tar.bz2", ".tar.xz", ".tar.lz", ".tar.lzma", ".tar.lzo", ".tar.lz4",
                      ".tar.lzop", ".log", ".md", ".txt", ".json", ".yaml", ".sh", ".bat", ".cmd", ".sql", ".xls",
                      ".xlsx", ".csv"}

# Initialize counters
processed_files = 0
total_files = 0


def should_exclude(path):
    """
    Check if the given path should be excluded based on directory name or file extension.
    """
    name = os.path.basename(path)
    if name in EXCLUDE_DIRS:
        return True
    return any(name.endswith(ext) for ext in EXCLUDE_EXTENSIONS)


def copy_modified_file(source_file, dest_dir):
    """
    Copy the modified file from source to destination.
    """
    global processed_files
    relative_path = os.path.relpath(source_file, source_dir)
    dest_file = os.path.join(dest_dir, relative_path)
    dest_dir = os.path.dirname(dest_file)
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir, exist_ok=True)

    shutil.copy2(source_file, dest_file)
    processed_files += 1
    print(f"Processed: {relative_path} ==> Copied: {dest_file}")


def process_files():
    """
    Walk through the source directory and process files.
    """
    global total_files
    global processed_files
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = []
        for root, dirs, files in os.walk(source_dir):
            dirs[:] = [d for d in dirs if not should_exclude(d)]
            for file in files:
                if should_exclude(file):
                    continue
                file_path = os.path.join(root, file)
                file_mtime = os.path.getmtime(file_path)
                if datetime.fromtimestamp(file_mtime) > start_time:
                    futures.append(executor.submit(copy_modified_file, file_path, dest_dir_entry.get()))
                    total_files += 1

        # Wait for all tasks to complete and update progress
        for future in as_completed(futures):
            future.result()

    # Ensure total_files is not zero to avoid division by zero
    progress_percentage = (processed_files / total_files) * 100 if total_files > 0 else 0
    messagebox.showinfo("Completion",
                        f"Processed {processed_files} out of {total_files} files ({progress_percentage:.2f}%)")
    total_files = 0
    processed_files = 0


def browse_source_dir():
    global source_dir
    source_dir = filedialog.askdirectory()
    source_dir_entry.delete(0, 'end')
    source_dir_entry.insert(0, source_dir)


def browse_dest_dir():
    global dest_dir
    dest_dir = filedialog.askdirectory()
    dest_dir_entry.delete(0, 'end')
    dest_dir_entry.insert(0, dest_dir)


def start_processing():
    global source_dir, dest_dir, start_time
    source_dir = source_dir_entry.get()
    dest_dir = dest_dir_entry.get()
    start_time = datetime.strptime(start_time_entry.get(), "%Y-%m-%d %H:%M")

    if not source_dir or not dest_dir or not start_time:
        messagebox.showerror("Error",
                             "Please select both source and destination directories and enter a valid start time.")
        return

    process_files()


# Create the main window
root = tk.Tk()
root.title("文件检测小程序")

# 设置默认值
default_source_folder = "D:\\goodcol\\jiujiang"
Label(root, text="监测文件夹:").grid(row=0, column=0, padx=10, pady=10)
source_dir_entry = Entry(root, width=50)
source_dir_entry.insert(0, default_source_folder)  # 设置默认值
source_dir_entry.grid(row=0, column=1, padx=10, pady=10)

# Destination directory entry
default_output_folder = "D:\\imp_data"
Label(root, text="输出文件夹:").grid(row=1, column=0, padx=10, pady=10)
dest_dir_entry = Entry(root, width=50)
dest_dir_entry.insert(0, default_output_folder)  # 设置默认值
dest_dir_entry.grid(row=1, column=1, padx=10, pady=10)

# Start time entry
Label(root, text="文件变动截止时间(YYYY-MM-DD HH:MM):").grid(row=2, column=0, padx=10, pady=10)
start_time_entry = Entry(root, width=50)
start_time_entry.grid(row=2, column=1, padx=10, pady=10)

# Start button
Button(root, text="开始执行", command=start_processing).grid(row=3, column=1, padx=10, pady=10)

# Run the application
root.mainloop()
